home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / comms / other / slrn / slrn_src / src / spool.c < prev    next >
C/C++ Source or Header  |  1999-05-14  |  34KB  |  1,489 lines

  1. /* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
  2.  *
  3.  * This file is part of slrn.
  4.  *
  5.  * Slrn is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License as published by the
  7.  * Free Software Foundation; either version 2, or (at your option) any
  8.  * later version.
  9.  * 
  10.  * Slrn is distributed in the hope that it will be useful, but WITHOUT
  11.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13.  * for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with Slrn; see the file COPYING.  If not, write to the Free
  17.  * Software Foundation, 59 Temple Place - Suite 330, 
  18.  * Boston, MA  02111-1307, USA.
  19.  */
  20.  
  21. /* Local spool support for slrn added by Olly Betts <olly@mantis.co.uk> */
  22. #include "config.h"
  23. #include "slrnfeat.h"
  24.  
  25. #define DEBUG_SPOOL 0
  26. #define DEBUG_SPOOL_FILENAME "SLRNDEBUG"
  27.  
  28. #include <stdio.h>
  29.  
  30. #ifdef HAVE_STDLIB_H
  31. # include <stdlib.h>
  32. #endif
  33.  
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <ctype.h>
  37.  
  38. #ifdef HAVE_UNISTD_H
  39. # include <unistd.h>
  40. #endif
  41.  
  42. #include <slang.h>
  43. #include "jdmacros.h"
  44.  
  45. #include <time.h>
  46.  
  47. #include "misc.h"
  48. #include "slrn.h"
  49. #include "slrndir.h"
  50.  
  51. #ifndef SLRN_SPOOL_ROOT
  52. # define SLRN_SPOOL_ROOT "/var/spool/news" /* a common place for the newsspool */
  53. #endif
  54.  
  55. #ifndef SLRN_SPOOL_NOV_ROOT
  56. # define SLRN_SPOOL_NOV_ROOT SLRN_SPOOL_ROOT
  57. #endif
  58.  
  59. #ifndef SLRN_SPOOL_NOV_FILE
  60. # define SLRN_SPOOL_NOV_FILE ".overview"
  61. #endif
  62.  
  63. #include <sys/types.h>
  64. #include <sys/stat.h>
  65. #include <assert.h>
  66.  
  67. #include <limits.h>
  68.  
  69. static int spool_put_server_cmd (char *, char *, unsigned int );
  70. static int spool_select_group (char *, int *, int *);
  71. static void spool_close_server (void);
  72. static int spool_has_cmd (char *);
  73. static int spool_initialize_server (void);
  74. static char *spool_read_line (char *, unsigned int );
  75. static int spool_xpat_cmd (char *, int, int, char *);
  76. static int spool_xgtitle_cmd (char *);
  77. static int spool_select_article (int, char *);
  78. static int spool_xhdr_command (char *, int, char *, unsigned int);
  79. static int spool_list_newsgroups (void);
  80. static int spool_list_active (void);
  81. static char *spool_read_xover (char *, unsigned int);
  82. static char *spool_read_xpat (char *, unsigned int);
  83. static int spool_article_num_exists (int);
  84.  
  85. static Slrn_Server_Obj_Type Spool_Server_Obj;
  86.  
  87. /* some state that the NNTP server would take care of if we were using one */
  88. static FILE *Spool_fh_local=NULL;
  89. static char *Spool_Group=NULL;
  90. static char *Spool_Group_Name;
  91.  
  92. static FILE *Spool_fh_nov=NULL; /* we use the overview file lots, so keep it open */
  93. static int Spool_cur_artnum = 0;
  94.  
  95. /* These are set when the group is selected. */
  96. static int Spool_Max_Artnum = 0;
  97. static int Spool_Min_Artnum = 0;
  98.  
  99. static int Spool_Doing_XOver;           /* if non-zero, reading from ,overview */
  100. static int Spool_Doing_XPat;           /* reading xpat */
  101. static int Spool_fhead=0; /* if non-0 we're emulating "HEAD" so stop on blank line */
  102. static int Spool_fFakingActive=0; /* if non-0 we're doing funky stuff with MH folders */
  103.  
  104. static int spool_fake_active( char *);
  105. static char *spool_fakeactive_read_line(char *, int);
  106. static int Spool_fakeactive_newsgroups=0;
  107.  
  108. #if DEBUG_SPOOL
  109. # include <stdarg.h>
  110. static void spool_debug (char *fmt, ...)
  111. {
  112.    FILE *fp = NULL;
  113.    va_list ap;
  114.  
  115.    if (fp == NULL)
  116.      {
  117.     fp = fopen (DEBUG_SPOOL_FILENAME, "w");
  118.     if (fp == NULL)
  119.       return;
  120.      }
  121.  
  122.    fprintf (fp, "%lu: ", (unsigned long) clock ());
  123.  
  124.    if (fmt == NULL)
  125.      {
  126.     fputs ("(NULL)", fp);
  127.      }
  128.    else
  129.      {
  130.     va_start(ap, fmt);
  131.     vfprintf(fp, fmt, ap);
  132.     va_end (ap);
  133.      }
  134.  
  135.    putc ('\n', fp);
  136.    fflush (fp);
  137. }
  138. #endif
  139.  
  140. /* close any current file (unless it's the overview file) and NULL the FILE* */
  141. static int spool_fclose_local (void)
  142. {
  143.    int res = 0;
  144.  
  145.    Spool_fhead=0;
  146.    Spool_fFakingActive=0;
  147.  
  148.    if (Spool_fh_local != NULL)
  149.      {
  150.     if (Spool_fh_local != Spool_fh_nov)
  151.       res = fclose(Spool_fh_local);
  152.     Spool_fh_local=NULL;
  153.      }
  154.    return res;
  155. }
  156.  
  157. static FILE *spool_open_nov_file (void)
  158. {
  159.    char *p, *q;
  160.    FILE *fp;
  161.    
  162.    /* The spool_dircat function will exit if it fails to malloc. */
  163.    p = slrn_spool_dircat (Slrn_Nov_Root, Spool_Group_Name, 1);
  164.    q = slrn_spool_dircat (p, Slrn_Nov_File, 0);
  165.    
  166.    fp = fopen (q,"rb");
  167.    SLFREE(q);
  168.    SLFREE(p);
  169.    
  170.    return fp;
  171. }
  172.  
  173. static int Spool_XOver_Next;
  174. static int Spool_XOver_Max;
  175. static int Spool_XOver_Min;
  176.  
  177. static int spool_nntp_xover (int min, int max)
  178. {
  179.    int i, ch;
  180.    long fp;
  181.  
  182. #if DEBUG_SPOOL
  183.    spool_debug ("spool_nntp_xover(%d,%d)", min, max);
  184. #endif
  185.    
  186.    Spool_Doing_XOver = 0;
  187.  
  188.    spool_fclose_local ();
  189.  
  190.    if (max > Spool_Max_Artnum)
  191.      max = Spool_Max_Artnum;
  192.    
  193.    if (min < Spool_Min_Artnum)
  194.      min = Spool_Min_Artnum;
  195.    
  196.    if (Spool_Server_Obj.sv_has_xover)
  197.      {
  198.     Spool_fh_local = Spool_fh_nov;
  199.     if (Spool_fh_local == NULL)
  200.       return -1;
  201.  
  202.     /* find first record in range in overview file */
  203.     /* first look at the current position and see where we are */
  204.     /* this is worth trying as slrn will often read a series of ranges */
  205.     fp = ftell (Spool_fh_local);
  206.  
  207.     if ((1 != fscanf (Spool_fh_local,"%d", &i))
  208.         || (i > min))
  209.       {
  210.          /* looks like we're after the start of the range */
  211.          /* therefore we'll have to rescan the file from the start */
  212.          rewind (Spool_fh_local);
  213.          i = -1;
  214.          /* this might be improved by doing some binary-chop style searching */
  215.       }
  216.     else
  217.       {
  218.          while (((ch = getc(Spool_fh_local)) != '\n')
  219.             && (ch != EOF))
  220.            ; /* do nothing */
  221.          
  222.          if (ch == EOF)
  223.            {
  224.           rewind (Spool_fh_local);
  225.           i = -1;
  226.            }
  227.       }
  228.  
  229. #if DEBUG_SPOOL
  230.     spool_debug ("Starting with i=%d",i);
  231. #endif
  232.  
  233.     while (i < min)
  234.       {
  235.          fp = ftell( Spool_fh_local );
  236.          if (1 != fscanf(Spool_fh_local,"%d", &i))
  237.            return -1;
  238.  
  239.          while (((ch = getc (Spool_fh_local)) != '\n')
  240.             && (ch != EOF))
  241.            ; /* do nothing */
  242.       }
  243. #ifndef SEEK_SET
  244. # define SEEK_SET    0
  245. #endif
  246.     fseek (Spool_fh_local, fp, SEEK_SET); /* reset to start of line */
  247.      }
  248.  
  249.    Spool_XOver_Next = Spool_XOver_Min = min;
  250.    Spool_XOver_Max = max;
  251.    Spool_Doing_XOver = 1;
  252.    
  253.    return OK_XOVER;
  254. }
  255.  
  256. static char *spool_read_xover (char *the_buf, unsigned int len)
  257. {
  258.    char *p;
  259.    long pos;
  260.  
  261. #if DEBUG_SPOOL
  262.    spool_debug ("spool_read_xover");
  263. #endif
  264.  
  265.    if (Spool_Doing_XOver == 0)
  266.      return NULL;
  267.  
  268.    if (Spool_XOver_Next > Spool_XOver_Max) 
  269.      {
  270.     Spool_Doing_XOver = 0;
  271.     return NULL;
  272.      }
  273.  
  274.    while (1)
  275.      {
  276.     unsigned int buflen;
  277.  
  278.     pos = ftell (Spool_fh_nov);
  279.    
  280.     if (NULL == (p = fgets (the_buf, len, Spool_fh_nov)))
  281.       {
  282.          Spool_Doing_XOver = 0;
  283.          return NULL;
  284.       }
  285.     
  286.     buflen = strlen (the_buf);
  287.     if (buflen && (the_buf[buflen - 1] == '\n'))
  288.       the_buf [buflen - 1] = 0;
  289.    
  290.     /* check if we've reached the end of the requested range */
  291.     Spool_XOver_Next = atoi (p);
  292.     if (Spool_XOver_Next > Spool_XOver_Max)
  293.       {
  294.          fseek (Spool_fh_nov, pos, SEEK_SET);
  295.          Spool_Doing_XOver = 0;
  296.          return NULL;
  297.       }
  298.     
  299.     if (Slrn_Spool_Check_Up_On_Nov == 0)
  300.       break;
  301.     
  302.     /* check that the article file actually exists */
  303.     /* if not, this nov entry is defunct, so ignore it */
  304. #if DEBUG_SPOOL
  305.     spool_debug ("Nov entry %ld", Spool_XOver_Next);
  306. #endif
  307.     
  308.     if (0 == spool_article_num_exists (Spool_XOver_Next))
  309.       {
  310. #if DEBUG_SPOOL
  311.          spool_debug (" - OK");
  312. #endif
  313.          break;
  314.       }
  315.     
  316. #if DEBUG_SPOOL
  317.     spool_debug (" skipped!");
  318. #endif
  319.      }
  320.  
  321.    Spool_XOver_Next++;
  322.    return p;
  323. }
  324.  
  325. static int spool_find_artnum_from_msgid (char *msgid)
  326. {
  327.    char buf [4096];
  328.    char *p;
  329.    int n;
  330.    
  331. #if DEBUG_SPOOL
  332.    spool_debug ("spool_find_artnum_from_msgid('%s')", msgid);
  333. #endif
  334.  
  335.    if (Slrn_Server_Obj->sv_has_xover == 0)
  336.      {
  337.     unsigned int len = strlen (msgid);
  338.    
  339.     for (n = Spool_Min_Artnum; n <= Spool_Max_Artnum; n++)
  340.       {
  341.          if (-1 == spool_xhdr_command ("Message-Id", n, buf, sizeof (buf)))
  342.            continue;
  343.          
  344.          p = slrn_skip_whitespace (buf);
  345.          if (0 == strncmp (p, msgid, len))
  346.            return n;
  347.       }
  348.    
  349.     return -1;
  350.      }
  351.    
  352.    if (OK_XOVER != spool_nntp_xover (1, INT_MAX))
  353.      return -1;
  354.  
  355.    while (NULL != spool_read_xover (buf, sizeof(bu